#include "types.h"
#include "params.h"
#include "biscuit.h"
#include "lock.h"
#include "kfunc.h"
#include "util.h"
#include "kobj.h"
#include "cons.h"

// todo : 添加EOF

struct cons consbuf;
struct ko * consko;

/* 向对consbuf进行操作,操作成功返回1,操作失败返回0 */
#define CONSBUF_FULL(cons) (cons.cur+1 == cons.bg)
#define CONSBUF_EMPTY(cons) (cons.ed == cons.bg)
#define CONSBUF_CLEAR(cons) (cons.ed = cons.bg)
#define CONSBUF_GETC(cons) (CONSBUF_EMPTY(cons)?0:(cons.ring[cons.bg++]))
#define CONSBUF_BAK(cons) ((cons.bg == cons.cur)?0:cons.cur--)
#define CONSBUF_PUTC(cons,c) (CONSBUF_FULL(cons)?0:(cons.ring[cons.cur++]=c))
#define CONSBUF_CR(cons) (cons.ed = cons.cur)

#define BACKSPACE 0x100

void
cons_putc (int c) {
    if (c == BACKSPACE) {
        ll_putc ('\b');
        ll_putc (' ');
        ll_putc ('\b');
    } else {
        ll_putc (c);
    }
}

// int
// cons_write (int user_src)

void
cons_intrhdlr () {
    int c;
    c = ll_getc ();
    #define IS_CHR(c) (c >= ' ' && c <= '~')
    #define IS_DEL(c) (c == 0x7f)
    #define IS_CR(c) (c == '\r')
    #define IS_LF(c) (c == '\n')
    #define IS_EOF(c) (c == '^')
    if (IS_EOF (c)) {
        CONSBUF_CLEAR (consbuf);
        sleep_unlock (&consbuf.rlk);
    } else if (IS_CHR (c)) {
        CONSBUF_PUTC (consbuf, c);
        cons_putc (c);
    } else if (IS_DEL (c)) {
        CONSBUF_BAK (consbuf);
        cons_putc (BACKSPACE);
    } else if (IS_CR (c)) {
        c = '\n';
        CONSBUF_PUTC (consbuf, c);
        CONSBUF_CR (consbuf);
        cons_putc (c);
        // NOTE: 无需 SLEEPLK_BARRER, 因为没有调用先后顺序
        sleep_unlock (&consbuf.rlk);
    } else if (IS_LF (c)) {
        CONSBUF_PUTC (consbuf, c);
        CONSBUF_CR (consbuf);
        cons_putc (c);
        // NOTE: 无需 SLEEPLK_BARRER, 因为没有调用先后顺序
        sleep_unlock (&consbuf.rlk);
    } else {
        // do nothing...
    }
}

void
consinit () {
    bzero (&consbuf, sizeof (consbuf));
}

struct cons * 
getcons () {
    sleep_lock (&consbuf.rlk);
    return &consbuf;
}

int
read_cons (struct cons * con, void * to, unsigned int sz) {
    char c;
    int cnt = 0;
    //read:
    sleep_lock (&con->rlk);
    while (cnt < sz && (c = CONSBUF_GETC(consbuf))) {
        *(char *)to = c;
        to++;
        cnt++;
    }
    // NOTE: 可不读满
    // if (CONSBUF_EMPTY(consbuf)) {
    //     goto read;
    // } else {
    sleep_unlock (&con->rlk);
    // }
    return cnt;
}

int
write_cons (struct cons * con, void * from, unsigned int sz) {
    //char c;
    int cnt;
    sleep_lock (&con->wlk);
    for (cnt = 0; cnt < sz; cnt++) {
        cons_putc(*(char *) from);
        from++;
    }
    sleep_unlock (&con->wlk);
    return cnt;
}


int
read_consko (struct ko * o, void * to, unsigned int sz) {
    int retval;
    retval = read_cons ((struct cons*) o->ctx, to, sz);
    return retval;
}

int
write_consko (struct ko * o, void * from, unsigned int sz) {
    int retval;
    retval = write_cons ((struct cons*) o->ctx, from, sz);
    return retval;
}